package com.chinafree.business.controller;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.chinafree.business.model.param.ChatParam;
import com.chinafree.business.model.result.ChatResult;
import com.chinafree.business.service.impl.ChatServiceImpl;
import com.chinafree.common.utils.JWTUtils;
import com.chinafree.config.CustomSpringConfigurator;
import com.chinafree.model.enumeration.JWTValue;
import com.chinafree.model.po.ChUserCompany;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j

@Component
@ServerEndpoint("/ws/{token}")
public class MyWebSocket {

    /**
     *
     */
    static final Class<CustomSpringConfigurator> CLASS = CustomSpringConfigurator.class;
    //
    // //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static AtomicInteger onlineCount = new AtomicInteger(0);
    //
    // concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    private static ConcurrentHashMap<Long, MyWebSocket> myWebSocketConcurrentHashMap = new ConcurrentHashMap<>();

    // 用来存放 公司对应的在线用户
    private static ConcurrentHashMap<Long, Set<Long>> companyMapUser = new ConcurrentHashMap<>();

 
    private static ChatServiceImpl chatServiceImpl;
    // 
    private Session session;
    //
    private Long userId;

    private Integer roleId;

    private Long companyId;


    @Autowired
    public void setChatService(ChatServiceImpl chatService){
        MyWebSocket.chatServiceImpl= chatService;
    }
    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) {
        this.session = session;
        DecodedJWT tokenInfo = JWTUtils.getTokenInfo(token);
        Long userId = Long.valueOf(tokenInfo.getHeaderClaim(JWTValue.USER_ID.getValue()).asString());
        Integer roleId = Integer.valueOf(tokenInfo.getHeaderClaim(JWTValue.ROLE_ID.getValue()).asString());
        String s = tokenInfo.getHeaderClaim(JWTValue.COMPANY_ID.getValue()).asString();
        Long companyId = Long.valueOf(s);
        this.userId = userId;
        this.roleId = roleId;
        this.companyId = companyId;
        // role 1: employee 2:HR
        //
        if (roleId == 2) {
            companyMapUser.computeIfAbsent(companyId, p -> new HashSet<>());
            companyMapUser.get(companyId).add(userId);
        }
        if(myWebSocketConcurrentHashMap.get(userId)==null){
        myWebSocketConcurrentHashMap.put(userId, this);
        addOnlineCount(); // 在线数加1
        log.info("999999999999999999933333333333有新连接加入！当前在线人数为" + onlineCount.get()+"  --userId:"+userId+"   --roleId:"+roleId +"  --company");
    }
        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            log.info("io 异常");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        myWebSocketConcurrentHashMap.remove(this.userId);
        if (companyId != null && companyMapUser!=null && companyMapUser.get(companyId)!=null) {
            companyMapUser.get(companyId).remove(userId);
        }
        subOnlineCount(); // 在线数减1
        System.out.println("有一连接关闭！当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String jsonStr, Session session) {
        if (jsonStr.equals("ping")) {
           
        }
        log.info("来自客户端的消息:userId" + jsonStr);
        ChatParam chatParam = JSON.parseObject(jsonStr, ChatParam.class);
        if (this.roleId.equals(2)) {
            sendMessageToUser(chatParam.getToId(), chatParam.getMessage());
        } else if (this.roleId.equals(1)) {
            sendMessageToCompany(chatParam.getToId(), chatParam.getMessage());
        }
    }

    private void sendMessageToCompany(Long companyId, String message) {
        if(companyId==null){
            return;
        }
        ChatResult chatResult = new ChatResult();
        // chatResult.setFromUserId(this.userId);
        chatResult.setMessage(message);
        String chatResultJson = JSON.toJSONString(chatResult);
        // 消息保存在数据库
        ChUserCompany chUserCompany = ChUserCompany.builder().companyId(companyId).userId(this.userId).message(message)
                .fromUser(1).build();

        chatServiceImpl.insert(chUserCompany);
      
        if (companyId!=null && myWebSocketConcurrentHashMap.get(companyId) == null) {
            return;
        }
        try {
            if (companyMapUser.get(companyId) != null) {
                Set<Long> longs = companyMapUser.get(companyId);
                for (Long l : longs) {
                    myWebSocketConcurrentHashMap.get(userId).sendMessage(chatResultJson);
                }
            }
        } catch (IOException e) {
            log.info("io异常");
        }
    }
    // //群发消息
    // for (MyWebSocket item : webSocketSet) {
    // try {
    // item.sendMessage(message);
    // } catch (IOException e) {
    // e.printStackTrace();
    // }
    // }

    private void sendMessageToUser(Long userId, String message) {

        ChatResult chatResult = new ChatResult();
        // chatResult.setFromCompanyId(this.companyId);
        chatResult.setMessage(message);
        chatResult.setId(this.companyId);
        
        String chatResultJson = JSON.toJSONString(chatResult);
        // 消息保存在数据库
        ChUserCompany chUserCompany = new ChUserCompany();
        chUserCompany.setCompanyId(this.companyId);
        chUserCompany.setUserId(userId);
        chUserCompany.setMessage(message);
        chUserCompany.setFromUser(2);
        chatServiceImpl.insert(chUserCompany);
        if (myWebSocketConcurrentHashMap!=null && myWebSocketConcurrentHashMap.get(userId) == null) {
            return;
        }
        try {
            if( myWebSocketConcurrentHashMap.get(userId)!=null){
            myWebSocketConcurrentHashMap.get(userId).sendMessage(chatResultJson);}
        } catch (IOException e) {
            log.info("io:{}",e);
        }
    }

    /**
     * 发生错误时调用
     */

    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println(error);
        log.error(error.getMessage());
    }

    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    public static synchronized int getOnlineCount() {
        return onlineCount.get();
    }

    public static synchronized void addOnlineCount() {
        MyWebSocket.onlineCount.getAndIncrement();
    }

    public static synchronized void subOnlineCount() {
        MyWebSocket.onlineCount.decrementAndGet();
    }
}